#include <acoral.h>
#ifdef CFG_PLUGIN_FS 

#include <os_file.h>
#include <mem.h>
#include <core.h>
#include <tff.h>
#include "../include/loadapp.h"

//ELF文件头
Elf32_Ehd  ehd;
Elf32_Phdr phdr;
Elf32_Shdr shdr;


void acoral_loadapp(char* filename, acoral_u32 stack_size, acoral_char(*CurDirList)[11])
{
/*  １ 读ＥＬＦ文件头，确定内存大小
	２ 分配内存（内存大小＋堆栈）
	３ 读ＥＬＦ到内存，重定义ＧＯＴ段值
	４ creat_thread_common的相应步骤
程序映像示意
    stack_bottom  ========================
	                 ^               |
                     |   stack       | prog
       	            -----------------| space
     	              instruction    |
    	            -----------------|
    	                data         |
                  ========================
*/
	acoral_32* fp;
	acoral_32 i;
	acoral_32 len;
	acoral_u32* memp;           // 分配内存首地址指向.（栈底）
	acoral_u32* meme;           // 分配内存任务映像首址指向
	acoral_u32* memt;    
	acoral_u8   buf[32];
	acoral_u32  buf_len = sizeof(buf);
	acoral_u32  total_len = 0;
	acoral_32 ehd_len = sizeof(ehd);

	acoral_u32 num;

	fp = acoral_open(filename, FA_READ);

	if ( NULL == fp)
	{
		acoral_prints("\nerror: can not find the file.");
		return;  //  can find the file.
	}
	if((len = acoral_read(fp,&ehd, ehd_len)) != ehd_len)
	{
		acoral_prints("\nerror: not a avaiable file.");
		acoral_close(fp);
		return;  //　not a ELF file.
	}
	if (ehd.e_ident[0] != 0x7f || ehd.e_ident[1] != 'E' ||
		ehd.e_ident[2] != 'L'  || ehd.e_ident[3] != 'F')
	{
		acoral_prints("\nerror: not a avaiable file.");
		acoral_close(fp);
		return; // not a Elf file.
	}

	if (ehd.e_type != 3)
	{
		acoral_prints("\nerror: not a avaiable file for acoral.");
		acoral_close(fp);
		return;
	}

	// 在程序头表中存的第一项是必要的读到信息，全部需要
	//　其余的信息不是执行必须的，先要这部分。
	if (ehd.e_phnum == 0)
	{	//不存在程序头表，要做春余处理
		acoral_prints("\nerror: not a avaiable file for acoral...");
		acoral_close(fp);
		return;
	}
	acoral_lseek(fp, ehd.e_phoff);
	num= ehd.e_phnum;   len = ehd.e_phentsize;
	//for (i=0; i<num; i++)
	//{
	//	acoral_prints("\n");
		acoral_read(fp, &phdr, len);         //读文件头部映像信息
	//	acoral_print("%8x|",phdr.p_offset);
	//	acoral_print("%8x|",phdr.p_filesz);
	//	acoral_print("%8x|",phdr.p_memsz);
	//}

	if (stack_size <= ACORAL_MIN_STACK_SIZE)
		stack_size = ACORAL_MIN_STACK_SIZE;

	//开始拷贝，然后修改线程创建，那里不用堆栈内存分配了
	//更进一步的改进在将ＴＣＢ块也放到这部分空间之中
	memp = acoral_malloc(phdr.p_memsz+stack_size);
	if (NULL == memp)
	{
		acoral_prints("\nerror: can not run the file. no memory.");
		acoral_close(fp);
		return;
	}
	memt = memp+(stack_size);
	memt = memt+4;
	//acoral_print("\n addr :  %x \n" , memt );
	memt = memt - ((acoral_u32)memt%4);
	//acoral_print("\n addr :  %x \n" , memt );
	meme = memt;

	// 拷贝执行的数据
	total_len = 0;
	acoral_lseek(fp, 0);
	while((len = acoral_read(fp, buf, buf_len) ) > 0 && total_len <= phdr.p_filesz)
	{
		total_len += len;
		if (len >= buf_len && total_len <= phdr.p_filesz )
		{
			acoral_memcpy(memt, buf, buf_len);
			memt += (buf_len/4);
		}
		else
		{
			len = phdr.p_filesz+len - total_len;
			acoral_memcpy(memt, buf, len);
			memt += (len/4);
		}	
	}

	//bss　清0
	len = phdr.p_memsz - phdr.p_filesz;
	acoral_memset(memt, 0, len);

	// 看拷贝的数据是否正确
/*	acoral_prints("\n========================\n");
	len = 0 ;
	memt = meme;
	while (len < phdr.p_filesz)
	{
		acoral_print("%07x %08x %08x %08x %08x",
				memt, memt[0],memt[1],memt[2],memt[3]);
		memt+=4;
		len +=16;
		acoral_print("\n");
	}
	acoral_print("%07x ",memt);
	len=(phdr.p_filesz+16-len);
	while(len>0)
	{
		acoral_print("%08x ",memt);
		memt+=1;
		len -= 4;
	}
*/

	//重定位.got表

	//创建线程
	memt = meme+ehd.e_entry;   //入口点地址
	


	acoral_close(fp);
}

/*=====================================
 *   ＥＬＦ文件分析
 *=====================================*/
void acoral_readelf(char* filename, acoral_char(*CurDirList)[11])
{
	acoral_32* fp;
	acoral_32 i;
	acoral_32 len;
	Elf32_Word flag1,flag2,flag3;
	void* shname_table;
	acoral_32 ehd_len = sizeof(ehd);

	acoral_u32 num;

	fp = acoral_open(filename, FA_READ);

	if ( NULL == fp)
	{
		acoral_prints("\nerror: can not find the file.");
		return;  //  can find the file.
	}
	if((len = acoral_read(fp,&ehd, ehd_len)) != ehd_len)
	{
		acoral_prints("\nerror: not a ELF file.");
		acoral_close(fp);
		return;  //　not a ELF file.
	}
	if (ehd.e_ident[0] != 0x7f || ehd.e_ident[1] != 'E' ||
		ehd.e_ident[2] != 'L'  || ehd.e_ident[3] != 'F')
	{
		acoral_prints("\nerror: not a ELF file.");
		acoral_close(fp);
		return; // not a Elf file.
	}

	if (ehd.e_type != 3) 
	{
		acoral_prints("\nerror: not a avaiable elf file for acoral.");
		acoral_close(fp);
		return;
	}

	acoral_print("\n Entry Address: 0x%x", ehd.e_entry);

	// 在程序头表中存的第一项是必要的读到信息，全部需要
	//　其余的信息不是执行必须的，先要这部分。
	if (ehd.e_phnum != 0)
	{	
		acoral_lseek(fp, ehd.e_phoff);
	
		num= ehd.e_phnum;   len = ehd.e_phentsize;

		acoral_prints("\n=================");
		acoral_print("\n程序头部信息: %d", num);
		acoral_prints("\n=================");
		acoral_print("\n%10s|%8s|%8s|%8s|%8s|%8s|%8s",
				"type","offset-f","vaddr","paddr",
				"size1-f","size2-r","power");
		for (i=0; i<num; i++)
		{
			acoral_prints("\n");
			acoral_read(fp, &phdr, len);
			switch(phdr.p_type)
			{
			 case 0:acoral_prints("unused    |");break;
			 case 1:acoral_prints("load      |");break;
			 case 2:acoral_prints("dyn-info  |");break;
			 case 3:acoral_prints("--------  |");break;
			 case 4:acoral_prints("prog-info |");break;
			 case 5:acoral_prints("reserved  |");break;
			 case 6:acoral_prints("########  |");break;
			 default:acoral_prints("reserved |");
			}
			acoral_print("%8x|",phdr.p_offset);
			acoral_print("%8x|",phdr.p_vaddr);
			acoral_print("%8x|",phdr.p_paddr);
			acoral_print("%8x|",phdr.p_filesz);
			acoral_print("%8x|",phdr.p_memsz);

			flag1=phdr.p_flags&0x1;
			flag2=phdr.p_flags&0x2;
			flag3=phdr.p_flags&0x4;
			if(flag1==1)
				acoral_prints("x");
			if(flag2==2)
				acoral_prints("w");
			if(flag3==4)
				acoral_prints("r");
		}
	}

	if (ehd.e_shnum !=0)
	{
//		shdr=(Elf32_Shdr*)malloc(sizeof(Elf32_Shdr));
//		Shdr_offset=ehd->e_shoff+ehd->e_shentsize*ehd->e_shstrndx;
//		rewind(fp);
//		fseek(fp,Shdr_offset,SEEK_SET);
//		fread(shname_shdr,sizeof(struct Elf32_Shdr) , 1, fp);
//		S_offset=shname_shdr->sh_offset;
//		shname_table=malloc(shname_shdr->sh_size);
		
//		rewind(fp);
//		fseek(fp,S_offset,SEEK_SET);
//		fread(shname_table,shname_shdr->sh_size,1,fp);
		
//		acoral_lseek(fp, 0, SEEK_SET);
//		acoral_read(fp, &ehd, sizeof(Elf32_Ehd));

		num= ehd.e_shnum;  len = ehd.e_shentsize;
		acoral_lseek(fp, ehd.e_shoff);
	
		acoral_prints("\n=================");
		acoral_print("\n节头部信息: %d", num);
		acoral_prints("\n=================");
		
		acoral_print("\n%10s|%10s|%5s|%5s|%5s|%5s|%5s|%5s|%5s|%5s",
				"name","type","flags","addr","offs",
				"size","link","info","-----","esize");
		for(i=0;i<num;i++)
		{
			acoral_prints("\n");
			acoral_read(fp, &shdr,len);
			acoral_print("%10d|",shdr.sh_name);	//打印节名
			//type
			switch(shdr.sh_type)
			{
				case 0:acoral_print("%10s|","none");break;
				case 1:acoral_print("%10s|","prog-def");break;
				case 2:acoral_print("%10s|","symtab");
					  // print_Sym(shdr->sh_offset,shdr->sh_size);
					   break;
				case 3:acoral_print("%10s|","strtab");break;
				case 4:acoral_print("%10s|","==rel==");break;
				case 5:acoral_print("%10s|","hash");break;
				case 6:acoral_print("%10s|","dynamic");break;
				case 7:acoral_print("%10s|","note");break;
				case 8:acoral_print("%10s|","?????");break;
				case 9:acoral_print("%10s|","**rel**");break;
				case 10:acoral_print("%10s|","reserved");break;
				case 11:acoral_print("%10s|","dynsym");
						//print_Sym(shdr->sh_offset,shdr->sh_size);
											 break;
				default:acoral_print("%10x|",shdr.sh_type);
			}


			flag1=shdr.sh_flags&0x1;
			flag2=shdr.sh_flags&0x2;
			flag3=shdr.sh_flags&0x4;
			acoral_print("--");
			if(flag1==1) acoral_print("d");else acoral_prints("-");
			if(flag2==2) acoral_print("b");else acoral_prints("-");
			if(flag3==4) acoral_print("t");else acoral_prints("-");
			acoral_prints("|");

			acoral_print("%5x|",shdr.sh_addr);
			acoral_print("%5x|",shdr.sh_offset);
			acoral_print("%5x|",shdr.sh_size); 
		}/**/
	}

	acoral_prints("\n\n\n");

	acoral_close(fp);
}

/*===================================
 *
 *  十六进制读到一个文件，输出到终端
 *===================================*/

void acoral_hexdump(char* filename, acoral_char(*CurDirList)[11])
{
	acoral_u32 i;
	acoral_u32* fp;
	acoral_u32 len;
	acoral_u16 buf[8];
	acoral_u32 addr;
	acoral_u32 t = sizeof(buf);
	addr = 0;
	fp = acoral_open(filename, FA_READ);
	if(NULL == fp)
		return;

	while((len = acoral_read(fp, buf, t) ) > 0)
	{
		if (len >= 8 * 2)
		{
			acoral_print("%07x %04x %04x %04x %04x %04x %04x %04x %04x", 
				addr,buf[0], buf[1], buf[2],buf[3], buf[4], buf[5], buf[6], buf[7]);
			addr += 8*2;
		}
		else
		{
			i = 0;
			acoral_print("%07x ", addr);
			while(len > 0 && i< 7)
			{
				acoral_print("%04x ",buf[i]);
				len = len -4;
				i++;
			}
		}
		acoral_prints("\n");
	}

	acoral_close(fp);
}

#endif //CFG_PLUGIN_FS 
